home *** CD-ROM | disk | FTP | other *** search
- /*
- * Name: torus.cpp
- *
- * Author: Chris Bentley 1/17/98, ATI Research Inc. Marlborough, MA
- *
- * Description: a simple test app that demonstrates the benefit of
- * using the RAVE strip/fan triangle interface over using
- * individual discrete triangles. Essentially strips/fans
- * are over twice as fast as individual triangles.
- *
- * Revision History
- *
- * 1/19/98 CLB - initial version 1.0
- * 1/19/98 CLB - added moving context when window dragged
- * 1/19/98 CLB - bumped version to 1.1
- * 1/19/98 CLB - changed output to render time + actual fps
- * 1/20/98 CLB - bumped version to 1.2
- * 1/20/98 CLB - fixed moving window + RAVE context rect
- * 2/18/98 CLB - bumped version to 1.3
- * 2/18/98 CLB - changed non-strip version to call QADrawVTexture( ..., kQAVertexMode_Tri )
- * 3/8/98 CLB - bumped version to 1.4
- * 3/8/98 CLB - added support for draagging between multiple monitors
- *
- */
- /****************************************************************/
- /* headers */
- /****************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <Timer.h>
- #include "RAVE.h"
- #include "macros.h"
- #include "matrix.h"
-
- /****************************************************************/
- /* defines */
- /****************************************************************/
- #define LEFT 20
- #define TOP 40
- #define WIDTH 600
- #define HEIGHT 400
-
- #define BRICK_RES_ID 128
- #define SUN_RES_ID 129
-
- #define MBAR_RES_ID 128
-
- #define APPLE_MENU_ID 128
- #define FILE_MENU_ID 129
- #define CONTROL_MENU_ID 130
- #define ENGINE_MENU_ID 131
-
- #define QUIT_ITEM 1
-
- #define TRI_ITEM 1
- #define STRIP_ITEM 2
- #define TEX_ALPHA_ITEM 3
- #define NO_TEX_ALPHA_ITEM 4
-
- #define TRIANGLE 0
- #define STRIP 1
- #define NUM_STEPS 36
- #define MAX_WORLD_VERTS (NUM_STEPS+1)*(NUM_STEPS+1)
- #define MAX_SCREEN_VERTS (NUM_STEPS+1)*(NUM_STEPS+1)*6
-
- #define MAX_ENGINE 5
-
- /*
- * macro to load fields of TQAVTexture
- */
- #define ST( _v,_x,_y,_z,_invW,_a,_r,_g,_b,_uOverW,_vOverW,_kd_r,_kd_g,_kd_b,_ks_r,_ks_g,_ks_b ) \
- { \
- (_v).x = (_x); \
- (_v).y = (_y); \
- (_v).z = (_z); \
- (_v).invW = (_invW); \
- (_v).a = (_a); \
- (_v).r = (_r); \
- (_v).g = (_g); \
- (_v).b = (_b); \
- (_v).uOverW = (_uOverW); \
- (_v).vOverW = (_vOverW); \
- (_v).kd_r = (_kd_r); \
- (_v).kd_g = (_kd_g); \
- (_v).kd_b = (_kd_b); \
- (_v).ks_r = (_ks_r); \
- (_v).ks_g = (_ks_g); \
- (_v).ks_b = (_ks_b); \
- }
-
- #define SetRect( R, l, t, r, b ) (R)->left = (l), (R)->top = (t), (R)->right = (r), (R)->bottom = (b)
-
- /*
- * utility macros
- */
- #define USHRT_MAX 65535U
- #define ONE_SECOND 1000000
- #define MILLIONTHS 0.000001F
- #define INV_360 0.002777777
- #define rand() ((32767+Random()) * 1.0/65536.0)
-
- /****************************************************************/
- /* typedefs */
- /****************************************************************/
- typedef unsigned char UINT8;
- typedef unsigned short UINT16;
- typedef long INT32;
- typedef unsigned long UINT32;
-
- typedef struct object {
- int num_verts;
- int num_rave_verts;
- int num_strips;
- int num_verts_per_strip;
- VECT world[MAX_WORLD_VERTS];
- VECT tex[MAX_WORLD_VERTS];
- VECT screen[MAX_WORLD_VERTS];
- TQAVTexture verts[MAX_SCREEN_VERTS];
- } OBJECT;
-
- /****************************************************************/
- /* prototypes */
- /****************************************************************/
- /*
- * initialization functions
- */
- void InitMac( void );
- int InitWindow( void );
- int InitRAVE( void );
- TQAEngine *FindEngine( TQADevice *device );
- GDHandle FindWindowDevice( WindowPtr pWin );
- void FindWindowContentRect( WindowPtr pWin, Rect *r );
- int SetupRAVE( void );
- int SetupRAVETex( void );
- void MenuBarInit( void );
-
- /*
- * Event handling functions
- */
- void EventLoop( void );
- void HandleMouseDown( EventRecord *pevent );
- void HandleMenuChoice( INT32 i32menuChoice );
- void HandleAppleChoice( UINT32 u32TheItem );
- void HandleFileChoice( UINT32 u32TheItem );
- void HandleControlChoice( UINT32 u32TheItem );
- void AdjustControlMenu( void );
- void HandleEngineChoice( UINT32 u32TheItem );
-
- /*
- * utility functions
- */
- void Cleanup( void );
- void DisplayString( int x, int y, char *str );
- UINT32 MicrosecondCount( void );
- int LoadImageFromResource( short resID, UINT8 depth, UINT8 alpha,
- TQAImage *map, TQAImagePixelType *pixelType );
-
- /*
- * 3D object functions
- */
- void redraw( void );
- void gen_torus( float radius1, float radius2, OBJECT *obj );
- void convert( OBJECT *obj, int mode );
- void transform( OBJECT *obj );
- void render( OBJECT *obj );
-
- /*
- * matrix functions
- */
- void matrix_mult( MATRIX mat1, MATRIX mat2, MATRIX result );
- void vect_matrix_mult( VECT pt, MATRIX mat, VECT result );
- void load_matrix_rows( MATRIX R, VECT row1, VECT row2, VECT row3 );
- void set_view_matrix( MATRIX V, VECT lookat, VECT up, VECT eye, Rect *WinRect );
- void rotate_about_axis( VECT axis, FLOAT32 angle, MATRIX M );
-
- /****************************************************************/
- /* global variables */
- /****************************************************************/
- /*
- * RAVE variables
- */
- GDHandle gGDevice;
- TQADevice gDevice;
- TQAEngine *gEngine;
- TQADrawContext *gDrawContext;
- TQATexture *gpTex;
- TQABitmap *gpBit;
- TQAImage gImageTex;
- TQAImage gImageBit;
- TQAImagePixelType pixelType;
- unsigned long gflags = kQAContext_DoubleBuffer;
- TQARect gRect = { LEFT, LEFT+WIDTH, TOP, TOP+HEIGHT };
- TQAEngine *EngineList[MAX_ENGINE] = { NULL, NULL, NULL, NULL, NULL };
- char EngineNames[MAX_ENGINE][100];
- unsigned long gEngineID = 0;
-
- /*
- * window variables
- */
- MenuHandle gAppleMenu;
- MenuHandle gFileMenu;
- MenuHandle gControlMenu;
- MenuHandle gEngineMenu;
- Boolean gbDone = false;
- Boolean gbTexAlpha = true;
- Boolean gbATIcard = false;
- int gNumEngines = 0;
- WindowPtr winPtr = NULL;
- Rect winRect = { TOP, LEFT, TOP+HEIGHT, LEFT+WIDTH };
- RGBColor BLACK = { 0, 0, 0 };
- GWorldPtr newGW;
- char str[256];
- OBJECT torus;
-
- /*
- * matrix utility variables
- */
- VECT _util_vect;
- FLOAT32 _util_FLOAT321;
- FLOAT32 _util_FLOAT322;
- MATRIX VPN;
- MATRIX R;
- VECT lookat = { 0, 0, 0, 1 };
- VECT up = { 0, 1, 0, 1 };
- VECT eye = { 0, 0, -10,1 };
- VECT axis = { 0.3, 1, 0.2, 0 };
- VECT axis0;
- int mode = TRIANGLE; //STRIP;
-
- /****************************************************************/
- /* code */
- /****************************************************************/
- /*
- * Function: main()
- *
- */
- void main( void )
- {
- /*
- * initialize Toolbox + window
- */
- InitMac();
-
- if( !InitWindow() || !InitRAVE() || !SetupRAVE() )
- {
- Cleanup();
- return;
- }
-
- set_view_matrix( VPN, lookat, up, eye, &winRect );
- rotate_about_axis( axis, DEG2RAD(5), R );
- gen_torus( 2.0, 4.0, &torus );
- redraw();
-
- EventLoop();
-
- /*
- * end
- */
- Cleanup();
- }
-
- /*
- * Function: InitMac()
- *
- */
- void InitMac( void )
- {
- OSErr error;
- SysEnvRec theWorld;
-
- /*
- * Test the computer to be sure we can do color.
- * If not we would crash, which would be bad.
- * If we can’t run, just beep and exit.
- */
- error = SysEnvirons( 1, &theWorld );
- if( theWorld.hasColorQD == false )
- ExitToShell();
-
- /*
- * Initialize all the needed managers.
- */
- InitGraf( &qd.thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( NULL );
- InitCursor();
-
- GetDateTime((unsigned long*) &qd.randSeed);
-
- MenuBarInit();
- }
-
- /*
- * Function: InitWindow()
- *
- */
- int InitWindow( void )
- {
- if( (winPtr = NewCWindow( NULL, &winRect, "\pStrip/Triangle Test", true,
- noGrowDocProc, (WindowPtr)-1, false, 0 )) == NULL )
- {
- printf( "ERROR: opening window\n" );
- return( false );
- }
-
- return( true );
- }
-
- /*
- * Function: InitRAVE()
- *
- */
- int InitRAVE( void )
- {
- Rect r;
-
- if( (gGDevice = FindWindowDevice(winPtr)) == NULL )
- {
- printf( "ERROR: No monitors found\n" );
- return( false );
- }
-
- gDevice.deviceType = kQADeviceGDevice;
- gDevice.device.gDevice = gGDevice;
-
- if( (gEngine = FindEngine( &gDevice )) == NULL )
- {
- printf( "ERROR: No Engine available\n" );
- return( false );
- }
-
- if( QAEngineCheckDevice( gEngine, &gDevice ) )
- {
- printf( "ERROR: EngineCheckDevice failed\n" );
- return( false );
- }
-
- FindWindowContentRect( winPtr, &r );
- OffsetRect( &r, -(**gGDevice).gdRect.left, -(**gGDevice).gdRect.top );
-
- gRect.left = r.left;
- gRect.top = r.top;
- gRect.right = r.right;
- gRect.bottom = r.bottom;
-
- return( true );
- }
-
- void FindWindowContentRect( WindowPtr pWin, Rect *r )
- {
- GrafPtr oldPort;
- Point leftTop;
- Point rightBot;
-
- GetPort( &oldPort );
-
- SetPort( pWin );
- SetPt( &leftTop, pWin->portRect.left, pWin->portRect.top );
- SetPt( &rightBot, pWin->portRect.right, pWin->portRect.bottom );
-
- LocalToGlobal( &leftTop );
- LocalToGlobal( &rightBot );
-
- SetRect( r, leftTop.h, leftTop.v, rightBot.h, rightBot.v );
-
- SetPort( oldPort );
- }
-
- /*
- * Function: FindWindowDevice()
- *
- */
- GDHandle FindWindowDevice( WindowPtr pWin )
- {
- GDHandle hDevice;
- Rect rWin;
- Rect intersect;
-
- if( pWin == NULL )
- return( NULL );
-
- rWin = ((*(((WindowPeek)pWin)->strucRgn))->rgnBBox);
-
- for( hDevice = GetDeviceList();
- hDevice;
- hDevice = GetNextDevice(hDevice) )
- {
- /*
- * test for active monitors that entirely contain rect
- */
- if( TestDeviceAttribute(hDevice, screenDevice) &&
- TestDeviceAttribute(hDevice, screenActive) &&
- SectRect(&rWin, &((*hDevice)->gdRect), &intersect) &&
- EqualRect(&rWin, &intersect) )
- {
- return( hDevice );
- }
- }
-
- return( NULL );
- }
-
- TQAEngine *FindEngine( TQADevice *device )
- {
- TQAEngine *tmpEngine;
- UINT32 vendorID;
- char Response[200];
- int i, len;
- int saveEngineID;
- Str255 menuStr;
- MenuHandle menuHndl = gEngineMenu;
-
- saveEngineID = gEngineID;
- gEngineID = 0;
-
- for( i = 0; i < gNumEngines; i++ )
- {
- CheckItem( gEngineMenu, i+1, false );
- DisableItem( gEngineMenu, i+1 );
- }
-
- /*
- * list all RAVE engines
- */
- for( tmpEngine = QADeviceGetFirstEngine(device);
- tmpEngine;
- tmpEngine = QADeviceGetNextEngine(device, tmpEngine) )
- {
- QAEngineGestalt( tmpEngine, kQAGestalt_ASCIIName, Response );
-
- /*
- * see if engine is already in list
- */
- for( i = 0; i < gNumEngines; i++ )
- {
- if( strcmp(Response, EngineNames[i]) == 0 )
- {
- EngineList[i] = tmpEngine;
- EnableItem( gEngineMenu, i+1 );
-
- if( i == saveEngineID )
- gEngineID = i;
- break;
- }
- }
-
- /*
- * if engine is not already in list add it
- */
- if( i == gNumEngines )
- {
- EngineList[gNumEngines] = tmpEngine;
- strcpy( EngineNames[gNumEngines], Response );
-
- menuStr[0] = strlen( Response );
- strcpy( (char *)(menuStr+1), Response );
-
- AppendMenu( gEngineMenu, menuStr );
-
- if( ++gNumEngines == MAX_ENGINE )
- break;
- }
- }
-
- if( gEngineID >= gNumEngines )
- gEngineID = 0;
-
- CheckItem( gEngineMenu, gEngineID+1, true );
-
- QAEngineGestalt( EngineList[gEngineID], kQAGestalt_VendorID, &vendorID );
- gbATIcard = (vendorID == 1);
-
- return( EngineList[gEngineID] );
- }
-
- int SetupRAVE( void )
- {
- if( !InitRAVE() )
- return( false );
-
- /*
- * create a draw context + set background color for clearing
- */
- if( QADrawContextNew(&gDevice,&gRect,0,gEngine,gflags,&gDrawContext) != kQANoErr )
- {
- printf( "ERROR: Context create failed\n" );
- return( false );
- }
-
- QASetFloat( gDrawContext, kQATag_ColorBG_a, 1.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_r, 1.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_g, 0.0 );
- QASetFloat( gDrawContext, kQATag_ColorBG_b, 0.0 );
-
- return( SetupRAVETex() );
- }
-
- int SetupRAVETex( void )
- {
- /*
- * load image for texture
- */
- if( !LoadImageFromResource(SUN_RES_ID, 16, gbTexAlpha, &gImageTex, &pixelType) )
- {
- printf( "ERROR: loading bitmap resource failed\n" );
- return( false );
- }
-
- /*
- * register texture with RAVE
- */
- QATextureNew( gEngine, kQATexture_None, pixelType, &gImageTex, &gpTex );
- if( gpTex == NULL )
- {
- printf( "ERROR: RAVE bitmap registration failed\n" );
- return( false );
- }
-
- QATextureDetach( gEngine, gpTex );
- DisposeGWorld( newGW );
-
- /*
- * set current texture
- */
- QASetPtr( gDrawContext, kQATag_Texture, gpTex );
-
- return( true );
- }
-
- void MenuBarInit( void )
- {
- Handle mBarHndl;
-
- mBarHndl = GetNewMBar( MBAR_RES_ID );
- SetMenuBar( mBarHndl );
-
- gAppleMenu = GetMenu( APPLE_MENU_ID );
- gFileMenu = GetMenu( FILE_MENU_ID );
- gControlMenu = GetMenu( CONTROL_MENU_ID );
- gEngineMenu = GetMenu( ENGINE_MENU_ID );
-
- AppendResMenu( gAppleMenu, 'DRVR' );
-
- DrawMenuBar();
-
- AdjustControlMenu();
- }
-
- void EventLoop( void )
- {
- EventRecord event;
-
- while( !gbDone )
- {
- WaitNextEvent( everyEvent, &event, 60L, NULL );
-
- switch( event.what )
- {
- case mouseDown: HandleMouseDown( &event ); break;
- case updateEvt: break;
- case nullEvent: break;
- default: break;
- }
- }
- }
-
- void HandleMouseDown( EventRecord *pevent )
- {
- WindowPtr pWin;
-
- switch( FindWindow( pevent->where, &pWin ) )
- {
- case inMenuBar: HandleMenuChoice( MenuSelect( pevent->where ) ); break;
- case inSysWindow: SystemClick( pevent, pWin ); break;
- case inGoAway: gbDone = (TrackGoAway(pWin, pevent->where) == true); break;
- case inContent: break;
- case inDrag: DragWindow( pWin, pevent->where, &qd.screenBits.bounds );
- Cleanup();
-
- if( !SetupRAVE() )
- Cleanup();
-
- redraw();
- break;
-
- default: break;
- }
- }
-
- void HandleMenuChoice( INT32 i32menuChoice )
- {
- if( i32menuChoice == 0 )
- return;
-
- switch( HiWord( i32menuChoice ) )
- {
- case APPLE_MENU_ID: HandleAppleChoice( LoWord(i32menuChoice) ); break;
- case FILE_MENU_ID: HandleFileChoice( LoWord(i32menuChoice) ); break;
- case CONTROL_MENU_ID: HandleControlChoice( LoWord(i32menuChoice) ); break;
- case ENGINE_MENU_ID: HandleEngineChoice( LoWord(i32menuChoice) ); break;
- default: break;
- }
-
- HiliteMenu( 0 );
- }
-
- void HandleAppleChoice( UINT32 u32TheItem )
- {
- Str255 strAccName;
-
- switch( u32TheItem )
- {
- default: GetMenuItemText( gAppleMenu, u32TheItem, strAccName );
- OpenDeskAcc( strAccName );
- break;
- }
- }
-
- void HandleFileChoice( UINT32 u32TheItem )
- {
- switch( u32TheItem )
- {
- case QUIT_ITEM: gbDone = true; break;
- default: break;
- }
- }
-
- void HandleControlChoice( UINT32 u32TheItem )
- {
- switch( u32TheItem )
- {
- case TRI_ITEM:
- mode = TRIANGLE;
- break;
-
- case STRIP_ITEM:
- mode = STRIP;
- break;
-
- case TEX_ALPHA_ITEM:
- gbTexAlpha = true;
-
- if( gpTex )
- QATextureDelete( gEngine, gpTex );
-
- if( !SetupRAVETex() )
- Cleanup();
- break;
-
- case NO_TEX_ALPHA_ITEM:
- gbTexAlpha = false;
-
- if( gpTex )
- QATextureDelete( gEngine, gpTex );
-
- if( !SetupRAVETex() )
- Cleanup();
- break;
-
- default:
- break;
- }
-
- AdjustControlMenu();
-
- redraw();
- }
-
- void AdjustControlMenu( void )
- {
- CheckItem( gControlMenu, TRI_ITEM, mode == TRIANGLE );
- CheckItem( gControlMenu, STRIP_ITEM, mode == STRIP );
- CheckItem( gControlMenu, TEX_ALPHA_ITEM, gbTexAlpha );
- CheckItem( gControlMenu, NO_TEX_ALPHA_ITEM, !gbTexAlpha );
- }
-
- void HandleEngineChoice( UINT32 u32TheItem )
- {
- UINT32 vendorID;
-
- for( int i = 1; i <= gNumEngines; i++ )
- CheckItem( gEngineMenu, i, false );
-
- gEngineID = u32TheItem-1;
- gEngine = EngineList[gEngineID];
-
- QAEngineGestalt( gEngine, kQAGestalt_VendorID, &vendorID );
- gbATIcard = (vendorID == 1);
-
- if( QAEngineCheckDevice( gEngine, &gDevice ) )
- printf( "ERROR: EngineCheckDevice failed\n" );
-
- CheckItem( gEngineMenu, u32TheItem, true );
-
- Cleanup();
-
- if( !SetupRAVE() )
- Cleanup();
-
- redraw();
- }
-
- /*
- * Function: Cleanup()
- *
- */
- void Cleanup( void )
- {
- if( gpTex )
- QATextureDelete( gEngine, gpTex );
-
- if( gDrawContext )
- QADrawContextDelete( gDrawContext );
- }
-
- /*
- * Function: DisplayString()
- *
- */
- void DisplayString( int x, int y, char *str )
- {
- if( !winPtr )
- return;
-
- SetPort( winPtr );
- RGBForeColor( &BLACK );
- MoveTo( x, y );
-
- str[0] = strlen( str+1 );
- DrawString( (const unsigned char *)str );
- }
-
- /*
- * Function: MicrosecondCount()
- *
- */
- UINT32 MicrosecondCount( void )
- {
- UnsignedWide currentCount;
-
- Microseconds(¤tCount);
-
- return( currentCount.lo );
- }
-
- /*
- * Function: LoadImageFromResource()
- *
- */
- int LoadImageFromResource( short resID, UINT8 depth, UINT8 alpha,
- TQAImage *map, TQAImagePixelType *pixelType )
- {
- PicHandle hPict;
- Rect pictRect;
- GDHandle saveGD;
- GWorldPtr saveGW;
- PixMapHandle pixHndl;
- PixMapPtr pixPtr;
-
- /*
- * determine target pixel type
- */
- switch( depth )
- {
- case 8: *pixelType = kQAPixel_CL8; break;
- case 16: *pixelType = (alpha) ? kQAPixel_ARGB16 : kQAPixel_RGB16; break;
- case 32: *pixelType = (alpha) ? kQAPixel_ARGB32 : kQAPixel_RGB32; break;
- default: return( false );
- }
-
- /*
- * load PICT resource and get bounding rect
- */
- if( (hPict = GetPicture( resID )) == NULL )
- return( false );
-
- pictRect = (**hPict).picFrame;
-
- /*
- * setup GWorld to draw pict into
- */
- GetGWorld( &saveGW, &saveGD );
-
- if( NewGWorld(&newGW, depth, &pictRect, NULL, NULL, NULL) != noErr )
- {
- ReleaseResource( (Handle)hPict );
- return( false );
- }
-
- LockPixels( newGW->portPixMap );
- SetGWorld( newGW, NULL );
-
- DrawPicture(hPict, &pictRect );
-
- /*
- * setup TQAImage struct with GWorld pixmap data
- */
- pixHndl = GetGWorldPixMap( newGW );
- pixPtr = *pixHndl;
- map->width = pictRect.right - pictRect.left;
- map->height = pictRect.bottom - pictRect.top;
- map->rowBytes = (UINT32)(pixPtr->rowBytes & 0x7fff);
- map->pixmap = GetPixBaseAddr( pixHndl );
-
- /*
- * Hack to demo sprite with alpha transparency -
- * detect white pixels (in 'Sun' PICT from Scrapbook)
- * and set their alpha bit to 0 for transparency
- */
- if( alpha )
- {
- UINT8 *u8ptr = (UINT8 *)map->pixmap;
- UINT16 *u16ptr;
-
- for( int y = 0; y < map->height; y++ )
- {
- u16ptr = (UINT16 *)u8ptr;
-
- for( int x = 0; x < map->width; x++ )
- {
- if( (u16ptr[x] & 0x7FFF) == 0x7FFF )
- u16ptr[x] &= 0x8000;
- else
- u16ptr[x] |= 0x8000;
- }
-
- u8ptr += map->rowBytes;
- }
- }
-
- /*
- * free PICT resource, delete temp GWorld,
- * and restore old GWorld
- */
- ReleaseResource( (Handle)hPict );
- SetGWorld( saveGW, saveGD );
-
- return( true );
- }
-
- void redraw( void )
- {
- UINT32 start, rstart, end;
- UINT32 count = 0;
- float time, rtime, fps;
- float sum = 0.0, rsum = 0.0;
-
- while( !Button() )
- {
- start = MicrosecondCount();
-
- transform( &torus );
- convert( &torus, mode );
-
- rstart = MicrosecondCount();
- render( &torus );
-
- /*
- * display frame rate
- */
- end = MicrosecondCount();
- time = (float)MAX((end-start),1)*MILLIONTHS;
- sum += 1.0/time;
-
- rtime = (float)MAX((end-rstart),1)*MILLIONTHS;
- rsum += rtime;
-
- count++;
- sprintf( str+1, "verts = %d tri = %d strip = %d render = %5.4fs avg = %5.4fs fps = %5.2f",
- torus.num_rave_verts,
- (mode == STRIP) ? torus.num_rave_verts-2*NUM_STEPS : torus.num_rave_verts/3,
- torus.num_strips, rtime, rsum/count, sum/count );
- DisplayString( 2, 10, str );
- }
- }
-
- /*
- * Function: gen_torus()
- *
- * Comments: generate vertex data for torus. First we generate
- * vertices around a circle of radius1. Then we translate
- * this by radius2, and rotate all the points around the
- * vertical (Y) axis.
- *
- * Inputs: radius1 - radius of circle cross-section of torus
- * radius2 - radius from center of doughnut to outer edge
- * obj - pointer to 3D object to store vertex list
- *
- * Returns: none
- */
- void gen_torus( float radius1, float radius2, OBJECT *obj )
- {
- int angle, ainc = 360/NUM_STEPS;
- int vert = 0;
- float r;
-
- /*
- * generate points around circle for
- * torus cross-section
- */
- for( angle = 0; angle <= 360; angle += ainc )
- {
- set_vect( obj->world[vert], radius1 * cos(DEG2RAD(angle)) + radius2, radius1 * sin(DEG2RAD(angle)), 0, 1 );
- set_vect( obj->tex[vert], 0, 1.0 - CLAMP(angle*INV_360,0,1), 0, 0 );
- vert++;
- }
-
- /*
- * sweep circle around vertical axis to generate
- * entire torus as surface of revolution
- */
- for( angle = ainc; angle <= 360; angle += ainc )
- {
- for( int i = 0; i <= NUM_STEPS; i++ )
- {
- r = obj->world[i][X];
- set_vect( obj->world[vert], r * cos(DEG2RAD(angle)), obj->world[i][Y], r * sin(DEG2RAD(angle)), 1.0 );
- set_vect( obj->tex[vert], CLAMP(angle*INV_360,0,1), obj->tex[i][1], 0, 0 );
- vert++;
- }
- }
-
- obj->num_verts = vert;
- }
-
- void convert( OBJECT *obj, int mode )
- {
- TQAVTexture *v = &obj->verts[0];
- int i, j;
- int n = 0;
- int col, ncol;
-
- obj->num_strips = 0;
- obj->num_rave_verts = 0;
-
- if( mode == STRIP )
- {
- for( j = 0; j < NUM_STEPS; j++ )
- {
- col = j*(NUM_STEPS+1);
- ncol = col + (NUM_STEPS+1);
-
- for( i = 0; i <= NUM_STEPS; i++ )
- {
- ST( *v, obj->screen[col+i][X], obj->screen[col+i][Y], obj->screen[col+i][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[col+i][0], obj->tex[col+i][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- ST( *v, obj->screen[ncol+i][X], obj->screen[ncol+i][Y], obj->screen[ncol+i][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[ncol+i][0], obj->tex[ncol+i][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
- }
-
- obj->num_strips++;
- }
-
- obj->num_verts_per_strip = 2*(NUM_STEPS+1);
- }
- else
- {
- for( j = 0; j < NUM_STEPS; j++ )
- {
- col = j*(NUM_STEPS+1);
- ncol = col + (NUM_STEPS+1);
-
- for( i = 0; i < NUM_STEPS; i++ )
- {
- /*
- * lower left triangle
- */
- ST( *v, obj->screen[col+i+1][X], obj->screen[col+i+1][Y], obj->screen[col+i+1][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[col+i+1][0], obj->tex[col+i+1][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- ST( *v, obj->screen[ncol+i+1][X], obj->screen[ncol+i+1][Y], obj->screen[ncol+i+1][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[ncol+i+1][0], obj->tex[ncol+i+1][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- ST( *v, obj->screen[col+i][X], obj->screen[col+i][Y], obj->screen[col+i][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[col+i][0], obj->tex[col+i][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- /*
- * upper right triangle
- */
- ST( *v, obj->screen[ncol+i+1][X], obj->screen[ncol+i+1][Y], obj->screen[ncol+i+1][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[ncol+i+1][0], obj->tex[ncol+i+1][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- ST( *v, obj->screen[ncol+i][X], obj->screen[ncol+i][Y], obj->screen[ncol+i][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[ncol+i][0], obj->tex[ncol+i][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
-
- ST( *v, obj->screen[col+i][X], obj->screen[col+i][Y], obj->screen[col+i][Z], 1.0,
- 1.0, 0.0, 0.0, 0.0,
- obj->tex[col+i][0], obj->tex[col+i][1],
- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
- v++; n++;
- }
- }
-
- obj->num_strips = 0;
- obj->num_verts_per_strip = 0;
- }
-
- obj->num_rave_verts = n;
- }
-
- void transform( OBJECT *obj )
- {
- for( int i = 0; i < obj->num_verts; i++ )
- {
- /*
- * rotate
- */
- vect_matrix_mult( obj->world[i], R, obj->world[i] );
-
- /*
- * project
- */
- vect_matrix_mult( obj->world[i], VPN, obj->screen[i] );
- homo_vect( obj->screen[i] );
- }
- }
-
- void render( OBJECT *obj )
- {
- QARenderStart( gDrawContext, NULL, NULL );
-
- if( obj->num_strips > 0 )
- {
- for( int i = 0; i < obj->num_strips; i++ )
- {
- QADrawVTexture( gDrawContext, obj->num_verts_per_strip, kQAVertexMode_Strip,
- obj->verts + i*obj->num_verts_per_strip, NULL );
- }
- }
- else
- {
- QADrawVTexture( gDrawContext, obj->num_rave_verts, kQAVertexMode_Tri, obj->verts, NULL );
- }
-
- QARenderEnd( gDrawContext, NULL );
- }
-
- /****************************************************************/
- /* matrix code */
- /****************************************************************/
- void matrix_mult( MATRIX mat1, MATRIX mat2, MATRIX result )
- {
- int i, j, k;
- FLOAT32 tmp;
-
- for( i = 0; i < 4; i++ )
- {
- for( j = 0; j < 4; j++ )
- {
- tmp = 0.0;
- for( k = 0; k < 4; k++ )
- tmp += mat1[i][k] * mat2[k][j];
- result[i][j] = tmp;
- }
- }
- }
-
- /******************************************************************/
- void vect_matrix_mult( VECT pt, MATRIX mat, VECT result )
- {
- int i, j;
- VECT r;
-
- for( i = 0; i < 4; i++ )
- {
- r[i] = 0.0;
- for( j = 0; j < 4; j++ )
- r[i] += mat[i][j] * pt[j];
- }
-
- copy_vect( result, r );
- }
-
- /******************************************************************/
- void load_matrix_rows( MATRIX R, VECT row1, VECT row2, VECT row3 )
- {
- int i;
-
- for( i = 0; i < 3; i++ )
- {
- R[0][i] = row1[i];
- R[1][i] = row2[i];
- R[2][i] = row3[i];
- R[3][i] = 0.0;
- }
-
- R[0][W] = 0.0;
- R[1][W] = 0.0;
- R[2][W] = 0.0;
- R[3][W] = 1.0;
- }
-
- /******************************************************************/
- void set_view_matrix( MATRIX VPN, VECT lookat, VECT up, VECT eye, Rect *WinRect )
- {
- VECT n, u, v;
- MATRIX R, invR, N, P, V, VP;
- MATRIX T, S, VT, VS, VT2;
- MATRIX PT, PS, TMP, TMP2;
- FLOAT32 dist, front, back;
- FLOAT32 umin, umax, vmin, vmax;
- FLOAT32 umid, vmid;
- FLOAT32 xscale, yscale, zscale;
- FLOAT32 scr_xmin, scr_ymin;
- FLOAT32 scr_xmax, scr_ymax;
- FLOAT32 scr_xdelta, scr_ydelta;
- FLOAT32 new_dist, zmin, zmax;
-
- /*
- * the values in the file specify the distance of
- * the view plane and clipping planes from the eye
- * point. We negate all of them, because once
- * the eye is at the origin they will all be in
- * the negative z range.
- */
- dist = 1.0;
- front = 0.1;
- back = 100.0;
-
- if( FLT_ZERO(dist) )
- dist = 0.1;
-
- umin = -1.0;
- umax = 1.0;
- vmin = -1.0;
- vmax = 1.0;
- umid = (umin + umax)/2.0;
- vmid = (vmin + vmax)/2.0;
-
- /*
- * initialize screen vieport min, max x,y values
- * as well as screen viewport x, y delta
- */
- scr_xmin = WinRect->left;
- scr_xmax = WinRect->right;
- scr_ymin = WinRect->top;
- scr_ymax = WinRect->bottom;
- scr_xdelta = (scr_xmax - scr_xmin);
- scr_ydelta = (scr_ymax - scr_ymin);
-
- /*
- * derive vector normal to view plane
- */
- sub_vect( eye, lookat, n );
- norm( n );
- norm( up );
-
- /*
- * generate view plane horizontal vector from
- * cross product of n and up vector
- */
- cross( up, n, u );
- norm( u );
-
- /*
- * generate true view plane up vector from
- * cross product of n and u vectors
- */
- cross( n, u, v );
- norm( v );
-
- /*
- * build rotation matrix from u, v, n
- * which are the vectors that will rotate
- * to become the world coordinate axes
- */
- ident_mat( R );
- load_matrix_rows( R, u, v, n );
- transpose_matrix( R, invR );
-
- /*
- * init translation of eye to world origin
- * and combine rotation, translation
- */
- init_trans( T, -eye[X], -eye[Y], -eye[Z] );
-
- matrix_mult( R, T, TMP );
-
- /*
- * set up scale matrix for converting to
- * normalized coordinates for clipping
- * against canonical view frustum
- * (equation 6.39 Foley & VanDam p.269)
- */
- xscale = (2.0 * dist)/((umax - umin)*(dist+back));
- yscale = (2.0 * dist)/((vmax - vmin)*(dist+back));
- zscale = 1.0/(dist+back);
-
- init_scale( S, xscale, yscale, zscale );
- matrix_mult( S, TMP, N );
-
- /*
- * calculate new view distance & zmin
- * (since they have been scaled by the
- * normalization transformation
- * (equation 6.40 Foley & VanDam p.270)
- */
- new_dist = dist * zscale;
- zmin = -(dist+front) * zscale;
- zmax = -(dist+back) * zscale;
-
- /*
- * set up matrix to transform to parallel
- * projection canonical clip volume
- * (equation 6.48 Foley & VanDam p.275)
- */
- ident_mat( P );
- P[3][Z] = 1.0/new_dist;
- P[3][W] = 0.0;
-
- /*
- * set up view transformation - here we are transforming
- * from normalized clip coordinates to screen coordinates
- * the clip coordinates range from -new_dist to +new_dist
- * because this is what the view plane normalized to -
- * (equation 6.54 Foley & VanDam p.278)
- */
- init_trans( VT, new_dist, new_dist, 0.0 );
- init_scale( VS, scr_xdelta/(2.0*new_dist), scr_ydelta/(2.0*new_dist), 1.0 );
- //init_trans( VT2, scr_xmin, scr_ymin, 0 ); RAVE takes care of this for us
-
- matrix_mult( VS, VT, V );
- matrix_mult( V, P, VP );
- matrix_mult( VP, N, VPN );
- }
-
- /*
- * Function:
- * rotate_about_axis() - generates 4x4 matrix to perform
- * rotation by given angle (radians) around an arbitrary
- * axis, as described in "Graphics Gems" on p.465.
- *
- * Inputs:
- * axis - VECT defining axis
- * angle - FLOAT32 defining angle of rotation in radians
- * M - 4x4 matrix to receive result
- *
- * Returns:
- * none
- */
- void rotate_about_axis( VECT axis, FLOAT32 angle, MATRIX M )
- {
- FLOAT32 sina, cosa, t;
- FLOAT32 x, y, z;
-
- norm( axis );
- x = axis[X];
- y = axis[Y];
- z = axis[Z];
-
- sina = sin( angle );
- cosa = cos( angle );
- t = 1.0 - cosa;
-
- ident_mat( M );
- M[0][0] = t * SQR(x) + cosa;
- M[0][1] = t * x * y + sina * z;
- M[0][2] = t * x * z - sina * y;
-
- M[1][0] = t * x * y - sina * z;
- M[1][1] = t * SQR(y) + cosa;
- M[1][2] = t * y * z + sina * x;
-
- M[2][0] = t * x * z + sina * y;
- M[2][1] = t * y * z - sina * x;
- M[2][2] = t * SQR(z) + cosa;
- }
-
-